home *** CD-ROM | disk | FTP | other *** search
/ Info-Mac 4 / Info_Mac IV CD-ROM (Pacific HiTech Inc.)(August 1994).iso / Development / Source / Controls GH ƒ / Flag Control GH / FlagCDEF.c < prev    next >
C/C++ Source or Header  |  1993-10-22  |  10KB  |  362 lines

  1. /************* Flag.c v 1.0
  2. *** an arrow CDEF for use when the app
  3. *** has a window that toggles between 
  4. *** minimum and extended views 
  5. By Glenn R. Howes 
  6. internet: howes@bert.chem.wisc.edu
  7. © 1993 by Glenn R. Howes 
  8. all rights reserved
  9. ***********/
  10. #include <GestaltEqu.h>
  11. #include "utilities.h"
  12. pascal long main(short variation, ControlHandle me,
  13.                 short msg, long param)
  14. {
  15.     long result = 0L;
  16.  
  17.     // msg's described in Inside Mac Vol 1 around pg 358
  18.     switch (msg)
  19.     {
  20.         case testCntl: // test mouse to see if in control
  21.             result = TestMe(me, HiWord(param), LoWord(param));
  22.         break;
  23.         case calcCRgns: // 24-bit mode method to calc drag region
  24.             result = CalcStripRegion(me, (RgnHandle)param);
  25.         break;
  26.         case initCntl: // should be first message, set up private data
  27.             InitMe(me);
  28.         break;
  29.         case dispCntl: // get rid of allocated memory
  30.             if ((*me)->contrlData)
  31.                 DisposeHandle((*me)->contrlData);
  32.         break;
  33.         case posCntl: // ignore, don't have thumb
  34.         break;
  35.         case thumbCntl: // ignore, don't have thumb
  36.         break;
  37.         case dragCntl: // ignore, don't have thumb
  38.         break;
  39.         case autoTrack: // not tested, should not be called
  40.             result = TrackMe(me, LoWord(param));
  41.         break;
  42.         case calcCntlRgn: // 32-bit method of calc gray region
  43.         case calcThumbRgn: // don't have thumb
  44.             CalcRegion(me, (RgnHandle)param);
  45.             result = 1L; 
  46.         // see tech note Control Manager Q&A's for why result = 1
  47.         break;
  48.         case drawCntl: // draw control, param indicates which part
  49.             DrawMe(me, LoWord(param));
  50.         break;
  51.     }
  52.     
  53.     return (result);
  54. }
  55. long TrackMe(ControlHandle me, short part) // shouldn't  be called
  56. {
  57.     Point        mouseLoc, oldPoint = {32767,32767};
  58.     Boolean        oldInRect = FALSE;
  59.     Boolean        inRect;
  60.     Point        vertices[3];
  61.     PenState    oldPenState;
  62.     GetPenState(&oldPenState);
  63.     PenNormal();
  64.     CalcVertices(vertices, &(*me)->contrlRect, 
  65.             GetCtlValue(me));
  66.     while(StillDown())
  67.     {
  68.         GetMouse(&mouseLoc);
  69.         if (oldPoint.v != mouseLoc.v 
  70.             || oldPoint.h != mouseLoc.h) // mouse has moved
  71.         {
  72.             inRect = PtInRect(mouseLoc, &(*me)->contrlRect);
  73.             if (inRect && !oldInRect)
  74.             {
  75.                 EraseRect(&(*me)->contrlRect);
  76.                 DrawLines(vertices);
  77.                 
  78.             }
  79.             else if (!inRect && oldInRect)
  80.             {
  81.                 DrawVertices(me, vertices);
  82.             }
  83.             oldPoint.v = mouseLoc.v;
  84.             oldPoint.h = mouseLoc.h;
  85.         }
  86.     }
  87.     DrawVertices(me, vertices);
  88.     SetPenState(&oldPenState);
  89. }
  90.  
  91. // under old  24-bit mode we will use this routine to calc the region
  92. // this control occupies. If the control manager wants just the
  93. // region of the thumb, the 31th bit of theRegion will be set
  94. long CalcStripRegion(ControlHandle me, RgnHandle theRegion)
  95. {
  96.     if (Using32Bit()) // WHY IS THIS GETTING CALLED
  97.     {
  98.         return (CalcRegion(me, theRegion));
  99.     }
  100.     else
  101.     {
  102.         theRegion = (RgnHandle)(0x7FFFFFFFL & (long)theRegion); 
  103.         // stripping out high bit only see tech note "joy of 32 bit clean"
  104.         return (CalcRegion(me, theRegion));
  105.     }
  106. }
  107. long CalcRegion(ControlHandle me, RgnHandle theRegion)
  108. {
  109.     RgnHandle    myRegion;
  110.     Point        vertices[3];
  111.  
  112.     myRegion = NewRgn();
  113.     if (myRegion)
  114.     {
  115.         OpenRgn();
  116.         CalcVertices(vertices, &(*me)->contrlRect, 
  117.             GetCtlValue(me));
  118.         DrawLines(vertices);
  119.         CloseRgn(myRegion);
  120.         InsetRgn(myRegion, -1, -1); // making region slightly larger than
  121.         // actual drawing to take into account width of lines
  122.         UnionRgn(theRegion, myRegion, theRegion);
  123.         DisposeRgn(myRegion);
  124.     }
  125.     return ((long)theRegion);
  126. }
  127. /******* TestMe ******
  128. ***** a mousedown has occurred or a track is underway, so I'm 
  129. *** being asked if a point is within my boundaries ********/
  130. long TestMe(ControlHandle me, short v, short h)
  131. {
  132.     Point            testPoint;
  133.     long            result = 0L;
  134.     
  135.     testPoint.h = h; testPoint.v = v;
  136.     if(PtInRect(testPoint, &(*me)->contrlRect))
  137.     {
  138.         result = inCheckBox; // It seems a reasonable part to use
  139.     }
  140.     return (result);
  141. }
  142. /********** InitMe *********
  143. **** I've just be allocated and I'm going to allocate some private
  144. **** data and initialize a few variables, including auxillary color
  145. **** information *********/
  146. void InitMe(ControlHandle me)
  147. {
  148.     PrivateHandle    privDataH;
  149.     AuxCtlHandle        acHndl;
  150.     CCTabHandle        tableH;
  151.     short            tabLen;
  152.     RGBColor        *tempColor;
  153.     privDataH = (PrivateHandle)NewHandleClear(sizeof(Private));
  154.     if (privDataH)
  155.     {
  156.         if ((*privDataH)->useColorQD = TestForColor())
  157.         {// we are using color, find the highlight color
  158.             tempColor = &(*privDataH)->frameColor;
  159.             tempColor->red = tempColor->blue = tempColor->green = 0; // black
  160.             tempColor = &(*privDataH)->fillColor; 
  161.             tempColor->green = tempColor->red = 39321; // baby blue
  162.             tempColor->blue = 65535;
  163.             GetAuxCtl(me, &acHndl);
  164.             if (acHndl)
  165.             {
  166.                 tableH = (*acHndl)->acCTable;
  167.                 tabLen = (*tableH)->ctSize;
  168.                 while(tabLen >= 0)
  169.                 {
  170.                     if ((*tableH)->ctTable[tabLen].value == cFrameColor)
  171.                     {
  172.                         BlockMove(&(*tableH)->ctTable[tabLen].rgb, 
  173.                             &(*privDataH)->frameColor, sizeof(RGBColor));
  174.                     }
  175.                     tabLen--;
  176.                 }
  177.             }
  178.         }
  179.         (*privDataH)->devicesAvailable = TrapAvailable(0xAA29);
  180.         (*privDataH)->oldValue = GetCtlValue(me);
  181.     }
  182.     (*me)->contrlData = (Handle)privDataH;
  183. }
  184.  
  185. void DrawMe(ControlHandle me, short parm)
  186. {
  187.     Point            vertices[3]; // a triangle
  188.     short            myValue, oldValue;
  189.     PrivateHandle    privData;
  190.     unsigned long    ticks;
  191.     
  192.     myValue = GetCtlValue(me);
  193.     privData = (PrivateHandle)(*me)->contrlData;
  194.     if (privData)
  195.     {
  196.         oldValue = (*privData)->oldValue;
  197.         if (oldValue != myValue) // the value is changed, animate the transition
  198.         {
  199.             CalcVertices(vertices, &(*me)->contrlRect, 
  200.                     2); // calculate diagonal arrow
  201.             EraseRect(&(*me)->contrlRect);
  202.             DrawVertices(me, vertices);
  203.             (*privData)->oldValue = myValue;
  204.             ticks = TickCount()+5;
  205.             while (ticks > TickCount()) 
  206.             // await 5/60ths of a second so its visibly turning
  207.             {
  208.                 // do nothing
  209.             }
  210.         }
  211.     }
  212.     // calc either an up or down arrow, erase the old arrow, and then draw it
  213.     CalcVertices(vertices, &(*me)->contrlRect, 
  214.             myValue); 
  215.     EraseRect(&(*me)->contrlRect);
  216.     DrawVertices(me, vertices);
  217. }
  218. /********* DrawLines ********
  219. ******* given a set of 3 points, draw lines connecting all three ****/
  220. void DrawLines(Point *vertices)
  221. {
  222.     MoveTo(vertices[0].h, vertices[0].v);
  223.     LineTo( vertices[1].h, vertices[1].v);
  224.     LineTo(vertices[2].h, vertices[2].v);
  225.     LineTo(vertices[0].h, vertices[0].v);
  226. }
  227. /******** DrawVertices ********
  228. ***** given 3 pre-calculated points, make a polygon,
  229. **** fill it if > 4 bit color is available and then
  230. **** frame it *******/
  231. void DrawVertices(ControlHandle me, Point *vertices)
  232. {
  233.     PrivateHandle    privData;
  234.     Boolean            useColorQD = FALSE;
  235.     PolyHandle        theFlag;
  236.     PenState        oldState;
  237.     Pattern        grayPattern;
  238.     privData = (PrivateHandle)(*me)->contrlData;
  239.     
  240.     useColorQD = UseColorQD(me, &(*me)->contrlRect); // my rectangle is > 4 bit color
  241.  
  242.     theFlag = OpenPoly();
  243.     if (theFlag)
  244.     {
  245.         DrawLines(vertices);
  246.         ClosePoly();
  247.         GetPenState(&oldState);
  248.         PenNormal();
  249.         if ((*me)->contrlHilite == 255) // disabled
  250.         {
  251.             if (useColorQD)
  252.             {
  253.                 RGBColor    oldColor, newColor; // semi-lite gray
  254.                 newColor.red = newColor.blue = newColor.green = 43690;
  255.                 GetForeColor(&oldColor);
  256.                 RGBForeColor(&newColor);
  257.                 FramePoly(theFlag);
  258.                 RGBForeColor(&oldColor);
  259.             }
  260.             else
  261.             {
  262.                 // first get a pattern that will simulate a dotted frame
  263.                 if (GetCtlValue(me)) // if we are pointing down use up and down line pat
  264.                     GetIndPattern(grayPattern, 0, 6);
  265.                 else
  266.                     GetIndPattern(grayPattern, 0, 25); // else side to side pat
  267.                 PenPat(&grayPattern);
  268.                 FramePoly(theFlag);
  269.             }
  270.         }
  271.         else // don't use gray out
  272.         {
  273.             if ((*me)->contrlHilite)
  274.             {
  275.                 PaintPoly(theFlag); // paint it black
  276.                 FramePoly(theFlag);
  277.             }
  278.             else if (useColorQD) // paint it blue
  279.             {
  280.                 RGBColor    oldColor;
  281.                 GetForeColor(&oldColor);
  282.                 RGBForeColor(&(*privData)->fillColor);
  283.                 // for some reason the constant patterns (ltGray, dkGray, black...) are
  284.                 // not available
  285.                 GetIndPattern(grayPattern, 0, 4);// medium grey
  286.                 PenPat(&grayPattern);
  287.                 PaintPoly(theFlag);
  288.                 GetIndPattern(grayPattern, 0, 1);// standard black for frame
  289.                 PenPat(&grayPattern);
  290.                 RGBForeColor(&(*privData)->frameColor);
  291.                 FramePoly(theFlag);
  292.                 RGBForeColor(&oldColor);
  293.                 
  294.             }
  295.             else // just use a simple unfilled triangle
  296.             {
  297.                 FramePoly(theFlag);
  298.             }
  299.             
  300.         }
  301.         SetPenState(&oldState);
  302.         KillPoly(theFlag);
  303.     }
  304. }
  305. /**************** CalcVertcices ***************
  306. **** given a rectangle to put it in, calc the vertices of
  307. **** a triangle which fill it in 3 possible ways
  308. *** 2: diagonal
  309. *** 1: pointing down
  310. *** 0: pointing to the right
  311. *** all triangles have a line passing through the center of the rectangle
  312. ***********/
  313. void CalcVertices(Point *vertices, Rect *ctlRect, short value)
  314. {
  315.     short    halfWidth, halfHeight;
  316.     Point    centerPoint;
  317.     long    delta;
  318.     Rect    theRect;
  319.     theRect.top = ctlRect->top +1;
  320.     theRect.left = ctlRect->left +1;
  321.     theRect.bottom = ctlRect->bottom -1;
  322.     theRect.right = ctlRect->right - 1;
  323.     
  324.     halfWidth = (theRect.right - theRect.left) /2; // don't want to go outside rect
  325.     halfHeight = (theRect.bottom - theRect.top) /2;
  326.     if (value == 2) // flag is pointing diagonally during animation
  327.     {
  328.         delta = (halfWidth > halfHeight)?halfHeight:halfWidth; // which is shorter
  329.         
  330.         delta = (delta * 707L) / 1000L; // multiply by the square root of 2 over 2
  331.         // delta is change in both the x and y coordinates from the center of 
  332.         // the rectangle
  333.         centerPoint.h = theRect.left + halfWidth;
  334.         centerPoint.v = theRect.top + halfHeight;
  335.         
  336.         vertices[0].h = centerPoint.h + delta;
  337.         vertices[0].v = centerPoint.v - delta; // top, right corner
  338.         vertices[1].h = centerPoint.h - delta;
  339.         vertices[1].v = centerPoint.v + delta; // bottom, left corner
  340.         vertices[2].h = vertices[0].h;
  341.         vertices[2].v = vertices[1].v; // bottom, right corner
  342.     }
  343.     else if (value) // flag is pointing down
  344.     {
  345.         vertices[0].h = theRect.left;
  346.         vertices[0].v = theRect.top + halfHeight;
  347.         vertices[1].h = theRect.right;
  348.         vertices[1].v = theRect.top + halfHeight;
  349.         vertices[2].h = theRect.left + halfWidth;
  350.         vertices[2].v = theRect.bottom;
  351.     }
  352.     else // flag is pointing to the right
  353.     {
  354.         vertices[0].h = theRect.left + halfWidth;
  355.         vertices[0].v = theRect.top;
  356.         vertices[1].h = theRect.left  + halfWidth;
  357.         vertices[1].v = theRect.bottom;
  358.         vertices[2].h = theRect.right;
  359.         vertices[2].v = theRect.top + halfHeight;
  360.     }
  361. }
  362.